#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/random.h>

#define PROCENTRY "probabilidad"
#define DEVICE "probabilidad"
static int cant_read=0; //cantidad de lecturas realizadas
static struct proc_dir_entry *procentry;
static int major;
static struct class *class;
static struct device *device;
static struct file_operations fops={
	.read = device_read
}

static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset);

//Funcion que se invoca cuando se escribe la entrada en /proc
int onwrite( struct file *filp, const char __user *buff, unsigned long len, void *data ){
	srandom32(buff[0]-'0');
	return len;
}
//Funcion que se invoca cuando se lee la entrada en /proc
int onread(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data){
	if(offset>0) return 0;
	else return sprintf(buffer,"%d\n",cant_read);
}
//Funcion que se invoca cuando se lee el device
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset){
	buffer[0] = ((char)(random32()%26))+'A'; //una letra random
	cant_read++;
	return 1;
}

//Funcion que se invoca al cargar el modulo
static int __init proba_init(void){
	printk(KERN_INFO "proba loaded.\n");
	//creo la entrada en /proc
	procentry=create_proc_entry( PROCENTRY, 0666, NULL );
	procentry->write_proc=onwrite;//callback cuando ocurre escritura
	procentry->read_proc=onread;//callback cuando ocurre lectura
	//creo el device en /dev
	major = register_chrdev(0, DEVICE, &fops);
	class = class_create(THIS_MODULE,"probabilidad");
	device= device_create(class, NULL, MKDEV(major,0),NULL,DEVICE);
	return 0;
}

static void __exit proba_exit(void){
	//elimino la entrada en /proc
	remove_proc_entry( PROCENTRY, NULL );
	//elimino el device
	device_destroy(class,MKDEV(major,0));
	class_unregister(class);
	class_destroy(class);
	unregister_chrdev(major, DEVICE);
	printk(KERN_INFO "proba unloaded.\n");
	return;
}

MODULE_LICENSE("GPL");
module_init( proba_init );
module_exit( proba_exit );
